package com.jintian.smart.kernel.common.expr.op.define;

import com.alibaba.fastjson.util.TypeUtils;
import com.jintian.smart.kernel.common.expr.datameta.BaseDataMeta;
import com.jintian.smart.kernel.common.expr.datameta.Constant;
import com.jintian.smart.kernel.common.expr.op.Operator;
import com.jintian.smart.kernel.core.expr.IllegalExpressionException;

import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Set;

/**
 * 加号操作实现 加号操作包括了数学加法和字符窜连接
 */
public class Op_PLUS extends Op_Base {
    public Op_PLUS() {
        super(Operator.PLUS);
    }

    public Constant execute(Constant[] args) throws IllegalExpressionException {
        Object[] params = this.getParameterValues(args);
        boolean numPlus = true;
        Set<Class<?>> argsTypes = new HashSet<>();
        for (Object p : params) {
            if (p == null || !Number.class.isAssignableFrom(p.getClass())) {
                numPlus = false;
                break;
            }
        }
        for (BaseDataMeta m : args) {
            argsTypes.add(m.mapTypeToJavaClass());
        }

        if (numPlus) {
            // 数字加
            BigDecimal value = TypeUtils.castToBigDecimal(params[0]).add(TypeUtils.castToBigDecimal(params[1]));
            if (argsTypes.contains(BigDecimal.class)) {
                return new Constant(BaseDataMeta.DataType.DATATYPE_BIGDECIMAL, value);
            } else if (argsTypes.contains(Double.class)) {
                return new Constant(BaseDataMeta.DataType.DATATYPE_DOUBLE, value.doubleValue());
            } else if (argsTypes.contains(Float.class)) {
                return new Constant(BaseDataMeta.DataType.DATATYPE_FLOAT, value.floatValue());
            } else if (argsTypes.contains(Long.class)) {
                return new Constant(BaseDataMeta.DataType.DATATYPE_LONG, value.longValue());
            } else {
                return new Constant(BaseDataMeta.DataType.DATATYPE_INT, value.intValue());
            }
        } else {
            // 字符加
            StringBuffer sb = new StringBuffer();
            for (Object p : params) {
                sb.append(p);
            }
            return new Constant(BaseDataMeta.DataType.DATATYPE_STRING, sb.toString());
        }
    }

    public Constant verify(int opPositin, BaseDataMeta[] args) throws IllegalExpressionException {
        this.checkParameterCount(opPositin, args);
        return new Constant(BaseDataMeta.DataType.DATATYPE_OBJECT, null);
    }
}
